#include "TabPage_grid.h"
#include "Style_grid.h"
#include <QVBoxLayout>
#include <QMessageBox>
#include <QFileDialog>
#include <QRegularExpression>

using namespace std;

void TabPage_grid::fillData(ConfigUI* conf) {
	// 1.将配置信息写入绘图控件
	m_config = conf;
	const Style_grid& sInfo = m_data->m_styleInfo;
	m_data->m_styles.getLineStyle(sInfo.flyLineKey)->setVisible(m_config->m_showFlyLines);
	m_data->m_styles.getLineStyle(sInfo.pathLineKey)->setVisible(m_config->m_showWires);
	m_data->m_styles.getPointStyle(sInfo.obsPtKey)->setVisible(m_config->m_showObss);
	m_data->m_styles.getPointStyle(sInfo.cornerPtKey)->setVisible(m_config->m_showCorners);
	m_data->m_styles.getPointStyle(sInfo.pathPtKey)->setVisible(m_config->m_showPathPts);
	m_data->m_styles.getPointStyle(sInfo.resPathPtKey)->setVisible(m_config->m_show_resPts);
	// 2.将文件数据写入数据对象
	m_dataAcquired = m_parser->readFile(m_qFullName);
	if (!m_dataAcquired) return;
	m_runFinished = false;
	// 3.创建绘图窗口Diagram
	shared_ptr<DiagramData> diagramData = std::static_pointer_cast<DiagramData>(
		std::shared_ptr<Data_grid>(m_data, [](auto*) {})); // 共享指针但不删除
	m_diagram = new Diagram(diagramData, m_config, this);
	m_algm = new AlgorithmLink_grid(m_data, m_config);
	// 4.设置布局
	QVBoxLayout* layout = new QVBoxLayout(this);
	layout->setContentsMargins(0, 0, 0, 0);
	layout->addWidget(m_diagram);
	setLayout(layout);
}
void TabPage_grid::refreshUI() {
	m_diagram->update();
};
// 槽函数
void TabPage_grid::action_reset() {
	// 复位重置，文本地图则重新读取文件，图片地图则读取其对应的文本文件
	m_data->clear();
	QString qFullName;
	if (m_qFileName.endsWith("jpg") || m_qFileName.endsWith("png") || m_qFileName.endsWith("jpeg")) {
		//图片地图
		QString txtName = QFileInfo(m_qFileName).completeBaseName() + ".map";
		qFullName = QDir(m_qFilePath).filePath(txtName);
	}
	else if (m_qFileName.endsWith("map")) {	//文本地图
		qFullName = QDir(m_qFilePath).filePath(m_qFileName);
	}
	else {
		return;
	}
	m_dataAcquired = m_parser->readFile(m_qFullName);
	refreshUI();
}
void TabPage_grid::action_random_pin() {
	// 重新生成随机pin
	const vector<QString>& symbols = m_data->m_mapSymbols;
	if (symbols.empty() || m_data->m_pinSum <= 0) return;
	int width = symbols[0].size();
	int height = symbols.size();
	m_data->m_flyLines = DataParser_grid::getRandomPts(width, height, m_data->m_pinSum);
	m_data->m_wires.clear();
	m_data->m_wiresPts.clear();
	refreshUI();
}
void TabPage_grid::pin_decrease() {
	// pin数量减少
	m_data->m_pinSum = (int)m_data->m_flyLines.size();
	if (m_data->m_pinSum <= 0) return;
	m_data->m_flyLines.pop_back();
	m_data->m_pinSum--;
	refreshUI();
}
void TabPage_grid::action_pin_increase() {
	// pin数量增加
	int width = m_data->maxPt.x() - m_data->minPt.x();
	int height = m_data->maxPt.y() - m_data->minPt.y();
	m_data->m_flyLines.emplace_back(DataParser_grid::getRandomPts(width, height, 1).back());
	m_data->m_pinSum = (int)m_data->m_flyLines.size();
	refreshUI();
}
void TabPage_grid::action_save_case() {
	m_qFullSaveName = QFileDialog::getSaveFileName(this,
		tr("保存json文件"),
		m_qFilePath,  // 拼接默认文件名 + "/" + defaltName
		tr("map files (*.map)")
	);
	bool saved = DataParser_grid::write_PPDT_case(m_qFullSaveName, m_data);
	if (saved)
		QMessageBox::information(this, tr("提示: "), tr("保存成功!"));
	else
		QMessageBox::warning(this, tr("警告: "), tr("保存失败!"));
}
void TabPage_grid::action_save_image() {
	// 1. 准备文件对话框参数
	QString imageFilters = tr("PNG 文件 (*.png);;JPEG 文件 (*.jpg *.jpeg);;BMP 文件 (*.bmp);;WebP 文件 (*.webp)");
	QString defaultPath = m_qFilePath.isEmpty() ? "./data" : m_qFilePath;
	QString defaultFileName = m_qFileName.isEmpty() ? "untitled.png" : QFileInfo(m_qFileName).completeBaseName() + ".png";
	// 2. 打开文件对话框
	QString selectedFilter;
	QString fileName = QFileDialog::getSaveFileName(
		this,
		tr("保存图片"),
		defaultPath + "/" + defaultFileName, // 默认文件名
		imageFilters,
		&selectedFilter
	);
	if (fileName.isEmpty()) {
		qDebug() << "用户取消保存";
		return;
	}
	// 3. 自动补全扩展名
	QString expectedSuffix = selectedFilter.section('*', 1).section(')', 0, 0);
	if (!fileName.endsWith(expectedSuffix, Qt::CaseInsensitive)) {
		fileName += expectedSuffix;
	}
	// 4. 获取当前绘图内容
	QPixmap pixmap = grab(); // 捕获整个控件
	if (pixmap.isNull()) {
		QMessageBox::critical(this, tr("错误"), tr("无法获取绘图内容"));
		return;
	}
	// 5. 根据格式选择保存参数
	QString suffix = QFileInfo(fileName).suffix().toLower();
	bool saveSuccess = false;
	if (suffix == "png") {
		saveSuccess = pixmap.save(fileName, "PNG", 100); // 无损压缩
	}
	else if (suffix == "jpg" || suffix == "jpeg") {
		saveSuccess = pixmap.save(fileName, "JPEG", 95); // 高质量JPEG
	}
	else if (suffix == "bmp") {
		saveSuccess = pixmap.save(fileName, "BMP");
	}
	else if (suffix == "webp") {
		saveSuccess = pixmap.save(fileName, "WEBP", 90);
	}
	else {
		QMessageBox::warning(this, tr("警告"),
			tr("不支持的格式，已自动保存为PNG格式"));
		saveSuccess = pixmap.save(fileName + ".png", "PNG");
	}
	// 6. 处理保存结果
	if (saveSuccess) {
		m_qFilePath = QFileInfo(fileName).absolutePath(); // 记住路径
		qDebug() << "图像已保存至:" << fileName;
		QMessageBox::information(this, tr("成功"), tr("图像保存成功"));
	}
	else {
		qDebug() << "保存失败:" << fileName;
		QMessageBox::critical(this, tr("错误"),
			tr("保存失败，请检查文件路径和权限"));
	}
}
void TabPage_grid::action_write_pre() {
	//判断是否已经完成预布线
	if (m_data->m_wires.empty()) {
		QMessageBox::warning(this, tr("提示: "), tr("请先进行预布线!"));
		return;
	}
	//设置默认名称
	QString defaltName;
	QFileInfo fileInfo(m_qFullSaveName);  // 解析路径
	QString lastFileBaseName = fileInfo.baseName();  // 获取纯文件名（如 "123.json"）
	QRegularExpression regex("^\\d+$");
	QRegularExpressionMatch match = regex.match(lastFileBaseName);
	if (match.hasMatch()) {
		bool ok;
		int num = match.captured(0).toInt(&ok);
		if (ok) {
			defaltName = QString::number(num + 1) + ".json";
		}
	}
	//弹出保存文件对话框
	m_qFullSaveName = QFileDialog::getSaveFileName(this,
		tr("保存json文件"),
		m_qFilePath + "/" + defaltName,  // 拼接默认文件名
		tr("json files (*.json)")
	);

	//m_qFullSaveName = QFileDialog::getSaveFileName(this, tr("保存json文件"), m_qFilePath, tr("json files (*.json)"));
	if (m_qFullSaveName.isEmpty()) {
		qDebug() << "用户取消了保存操作";
		return;
	}
	m_parser->setPtsFromLines(m_data->m_wires, m_data->m_wiresPts);
	DataParser_grid::write_PPDT_Pre(m_qFullSaveName, m_data->m_flyLines, m_data->m_wiresPts, m_data->m_mapSymbols);
	m_resAdded = false;
}
void TabPage_grid::action_write_res() {
	if (!m_resAdded) {
		bool writeSucessed = DataParser_grid::write_PPDT_Res(m_qFullSaveName, m_data->m_wiresPts, m_data->m_mapSymbols);
		if (writeSucessed) {
			m_resAdded = true;
			QMessageBox::information(this, tr("提示: "), tr("追加成功!"));
		}
		else {
			QMessageBox::warning(this, tr("警告: "), tr("追加失败!"));
		}
	}
	else {
		QMessageBox::warning(this, tr("警告: "), tr("禁止重复追加最终布线信息!"));
	}
	return;
}
void TabPage_grid::pressRunButton() {
	// 点击run按钮，如果未打开文件,即m_data为空指针，则弹窗提示并返回
	if (this == nullptr || m_data == nullptr) {
		QMessageBox::warning(this, "提示", "请先打开文件！");
		return;
	}
	cout << "pressRunButton" << endl;
	m_algm->routingRunBegin();
	m_algm->routingRun();
	m_parser->setPtsFromLines(m_data->m_wires, m_data->m_wiresPts);
	m_diagram->setData1();
	m_diagram->setData2();
	refreshUI();
}

// 推荐修复（假设 getPointStyle 是函数）：
void TabPage_grid::onConfigChanged() {
	const Style_grid& sInfo = m_data->m_styleInfo;
	m_data->m_styles.getLineStyle(sInfo.flyLineKey)->setVisible(m_config->m_showFlyLines);
	m_data->m_styles.getLineStyle(sInfo.pathLineKey)->setVisible(m_config->m_showWires);
	m_data->m_styles.getPointStyle(sInfo.obsPtKey)->setVisible(m_config->m_showObss);
	m_data->m_styles.getPointStyle(sInfo.cornerPtKey)->setVisible(m_config->m_showCorners);
	m_data->m_styles.getPointStyle(sInfo.pathPtKey)->setVisible(m_config->m_showPathPts);
	m_data->m_styles.getPointStyle(sInfo.resPathPtKey)->setVisible(m_config->m_show_resPts);
	refreshUI();
}
void TabPage_grid::tranformChanged() {
	m_diagram->initViewTransform();
	refreshUI();
}
void TabPage_grid::leftPressRun(SelectedTarget* target) {
	if (target->lineSelected) {
		m_algm->pushLineRunBegin(target->sLine, *target->linesToRun);
	}
	else if (target->pinSelected) {
		m_algm->pushPinRunBegin(target->nearistPt, *target->linesToRun);
	}
}
void TabPage_grid::leftPressMoveRun(SelectedTarget* target) {
	if (target->lineSelected) {
		m_algm->pushLineRun(target->offset, false, m_config->m_postOn);
	}
	else if (target->pinSelected) {
		m_algm->pushPinRun(target->offset, false);
	}
}
void TabPage_grid::leftReleaseRun(SelectedTarget* target) {
	if (target->lineSelected) {
		m_algm->pushLineRun(target->offset, m_config->m_onGrids, m_config->m_postOn);
	}
	else if (target->pinSelected) {
		m_algm->pushPinRun(target->offset, m_config->m_onGrids);
	}
	m_parser->setPtsFromLines(m_data->m_wires, m_data->m_wiresPts);
	m_diagram->setData1();
	m_diagram->setData2();
	refreshUI();
}